{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "classify ants and bees\n",
    "https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quoting these notes,\n",
    "\n",
    "    In practice, very few people train an entire Convolutional Network from scratch (with random initialization), because it is relatively rare to have a dataset of sufficient size. Instead, it is common to pretrain a ConvNet on a very large dataset (e.g. ImageNet, which contains 1.2 million images with 1000 categories), and then use the ConvNet either as an initialization or a fixed feature extractor for the task of interest.\n",
    "\n",
    "These two major transfer learning scenarios look as follows:\n",
    "\n",
    "    Finetuning the convnet: Instead of random initializaion, we initialize the network with a pretrained network, like the one that is trained on imagenet 1000 dataset. Rest of the training looks as usual.\n",
    "    ConvNet as fixed feature extractor: Here, we will freeze the weights for all of the network except that of the final fully connected layer. This last fully connected layer is replaced with a new one with random weights and only this layer is trained.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "# License: BSD\n",
    "# Author: Sasank Chilamkurthy\n",
    "\n",
    "from __future__ import print_function, division\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torch.optim import lr_scheduler\n",
    "import numpy as np\n",
    "import torchvision\n",
    "from torchvision import datasets, models, transforms\n",
    "import matplotlib.pyplot as plt\n",
    "import time\n",
    "import os\n",
    "import copy\n",
    "\n",
    "plt.ion()   # interactive mode"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load Data\n",
    "\n",
    "We will use torchvision and torch.utils.data packages for loading the data.\n",
    "\n",
    "The problem we’re going to solve today is to train a model to classify ants and bees. We have about 120 training images each for ants and bees. There are 75 validation images for each class. Usually, this is a very small dataset to generalize upon, if trained from scratch. Since we are using transfer learning, we should be able to generalize reasonably well.\n",
    "\n",
    "This dataset is a very small subset of imagenet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Data augmentation and normalization for training\n",
    "# Just normalization for validation\n",
    "data_transforms = {\n",
    "    'train': transforms.Compose([\n",
    "        transforms.RandomResizedCrop(224),\n",
    "        transforms.RandomHorizontalFlip(),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n",
    "    ]),\n",
    "    'val': transforms.Compose([\n",
    "        transforms.Resize(256),\n",
    "        transforms.CenterCrop(224),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n",
    "    ]),\n",
    "}\n",
    "\n",
    "data_dir = '/home/jinbo/gitme/dl-algorithm-coding/data/led'\n",
    "image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),\n",
    "                                          data_transforms[x])\n",
    "                  for x in ['train', 'val']}\n",
    "dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=8,\n",
    "                                             shuffle=True, num_workers=8)\n",
    "              for x in ['train', 'val']}\n",
    "dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}\n",
    "class_names = image_datasets['train'].classes\n",
    "\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Visualize a few images\n",
    "\n",
    "Let’s visualize a few training images so as to understand the data augmentations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def imshow(inp, title=None):\n",
    "    \"\"\"Imshow for Tensor.\"\"\"\n",
    "    inp = inp.numpy().transpose((1, 2, 0))\n",
    "    mean = np.array([0.485, 0.456, 0.406])\n",
    "    std = np.array([0.229, 0.224, 0.225])\n",
    "    inp = std * inp + mean\n",
    "    inp = np.clip(inp, 0, 1)\n",
    "    plt.imshow(inp)\n",
    "    if title is not None:\n",
    "        plt.title(title)\n",
    "    plt.pause(0.001)  # pause a bit so that plots are updated\n",
    "\n",
    "\n",
    "# Get a batch of training data\n",
    "inputs, classes = next(iter(dataloaders['train']))\n",
    "\n",
    "# Make a grid from batch\n",
    "out = torchvision.utils.make_grid(inputs)\n",
    "\n",
    "imshow(out, title=[class_names[x] for x in classes])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Training the model\n",
    "\n",
    "Now, let’s write a general function to train a model. Here, we will illustrate:\n",
    "\n",
    "    Scheduling the learning rate\n",
    "    Saving the best model\n",
    "\n",
    "In the following, parameter scheduler is an LR scheduler object from torch.optim.lr_scheduler."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_model(model, criterion, optimizer, scheduler, num_epochs=25):\n",
    "    since = time.time()\n",
    "    \n",
    "    best_model_wts = copy.deepcopy(model.state_dict())\n",
    "    best_acc = 0.0\n",
    "\n",
    "    for epoch in range(num_epochs):\n",
    "        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n",
    "        print('-' * 10)\n",
    "        # Each epoch has a training and validation phase\n",
    "        for phase in ['train', 'val']:\n",
    "            if phase == 'train':\n",
    "                scheduler.step()\n",
    "                model.train()  # Set model to training mode\n",
    "            else:\n",
    "                model.eval()   # Set model to evaluate mode\n",
    "\n",
    "            running_loss = 0.0\n",
    "            running_corrects = 0\n",
    "\n",
    "            # Iterate over data.\n",
    "            for inputs, labels in dataloaders[phase]:\n",
    "                inputs = inputs.to(device)\n",
    "                labels = labels.to(device)\n",
    "\n",
    "                # zero the parameter gradients\n",
    "                optimizer.zero_grad()\n",
    "\n",
    "                # forward\n",
    "                # track history if only in train\n",
    "                with torch.set_grad_enabled(phase == 'train'):\n",
    "                    outputs = model(inputs)\n",
    "                    # output 为 bs × 2的 tensor，但值有正负且绝对值可大于1\n",
    "                    _, preds = torch.max(outputs, 1)\n",
    "                    loss = criterion(outputs, labels)\n",
    "\n",
    "                    # backward + optimize only if in training phase\n",
    "                    if phase == 'train':\n",
    "                        loss.backward()\n",
    "                        optimizer.step()\n",
    "\n",
    "                # statistics\n",
    "                running_loss += loss.item() * inputs.size(0)\n",
    "                running_corrects += torch.sum(preds == labels.data)\n",
    "\n",
    "            epoch_loss = running_loss / dataset_sizes[phase]\n",
    "            epoch_acc = running_corrects.double() / dataset_sizes[phase]\n",
    "\n",
    "            \n",
    "            if epoch % 10 == 0:\n",
    "                \n",
    "                print('{} Loss: {:.4f} Acc: {:.4f}'.format(\n",
    "                phase, epoch_loss, epoch_acc))\n",
    "                time_elapsed = time.time() - since\n",
    "                print('has spend time {:.0f}m {:.0f}s/n'.format(\n",
    "                    time_elapsed // 60, time_elapsed % 60))\n",
    "\n",
    "            # deep copy the model\n",
    "            if phase == 'val' and epoch_acc > best_acc:\n",
    "                best_acc = epoch_acc\n",
    "                best_model_wts = copy.deepcopy(model.state_dict())\n",
    "\n",
    "        print()\n",
    "\n",
    "    time_elapsed = time.time() - since\n",
    "    print('Training complete in {:.0f}m {:.0f}s'.format(\n",
    "        time_elapsed // 60, time_elapsed % 60))\n",
    "    print('Best val Acc: {:4f}'.format(best_acc))\n",
    "\n",
    "    # load best model weights\n",
    "    model.load_state_dict(best_model_wts)\n",
    "    return model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Visualizing the model predictions\n",
    "\n",
    "Generic function to display predictions for a few images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "def visualize_model(model, num_images=6):\n",
    "    was_training = model.training\n",
    "    model.eval()\n",
    "    images_so_far = 0\n",
    "    fig = plt.figure()\n",
    "\n",
    "    with torch.no_grad():\n",
    "        for i, (inputs, labels) in enumerate(dataloaders['val']):\n",
    "            inputs = inputs.to(device)\n",
    "            labels = labels.to(device)\n",
    "\n",
    "            outputs = model(inputs)\n",
    "            _, preds = torch.max(outputs, 1)\n",
    "\n",
    "            for j in range(inputs.size()[0]):\n",
    "                images_so_far += 1\n",
    "                ax = plt.subplot(num_images//2, 2, images_so_far)\n",
    "                ax.axis('off')\n",
    "                ax.set_title('predicted: {}'.format(class_names[preds[j]]))\n",
    "                imshow(inputs.cpu().data[j])\n",
    "\n",
    "                if images_so_far == num_images:\n",
    "                    model.train(mode=was_training)\n",
    "                    return\n",
    "        model.train(mode=was_training)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finetuning the convnet\n",
    "\n",
    "Load a pretrained model and reset final fully connected layer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_ft = models.resnet18(pretrained=False)\n",
    "#model_ft = models.resnet18(pretrained=True)\n",
    "num_ftrs = model_ft.fc.in_features\n",
    "model_ft.fc = nn.Linear(num_ftrs, 2)\n",
    "\n",
    "model_ft = model_ft.to(device)\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "\n",
    "# Observe that all parameters are being optimized\n",
    "optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# Decay LR by a factor of 0.1 every 7 epochs\n",
    "exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Train and evaluate\n",
    "\n",
    "It should take around 15-25 min on CPU. On GPU though, it takes less than a minute."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0/9999\n",
      "----------\n",
      "train Loss: 0.3060 Acc: 0.8713\n",
      "has spend time 0m 7s/n\n",
      "val Loss: 0.0096 Acc: 1.0000\n",
      "has spend time 0m 9s/n\n",
      "\n",
      "Epoch 1/9999\n",
      "----------\n",
      "\n",
      "Epoch 2/9999\n",
      "----------\n",
      "\n",
      "Epoch 3/9999\n",
      "----------\n",
      "\n",
      "Epoch 4/9999\n",
      "----------\n",
      "\n",
      "Epoch 5/9999\n",
      "----------\n",
      "\n",
      "Epoch 6/9999\n",
      "----------\n",
      "\n",
      "Epoch 7/9999\n",
      "----------\n",
      "\n",
      "Epoch 8/9999\n",
      "----------\n",
      "\n",
      "Epoch 9/9999\n",
      "----------\n",
      "\n",
      "Epoch 10/9999\n",
      "----------\n"
     ]
    }
   ],
   "source": [
    "model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,\n",
    "                       num_epochs=10000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
